<?php

namespace App\Library;

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Processor\UidProcessor;
use Monolog\Processor\ProcessIdProcessor;


class LogLib
{
    /**
     * 实例化logger
     *
     * @var Logger[]
     */
    private static $_log_instance = [];

    /**
     * 获取log实例
     * 根据日志名称实例化logger,每个名称只实例化一次
     *
     * @param string $name
     * @return mixed
     */
    private static function getLogInstance(string $name)
    {
        if (!isset(static::$_log_instance[$name]) || static::$_log_instance[$name] === null) {
            static::$_log_instance[$name] = new Logger($name,
                                                       [
                                                           new StreamHandler(self::getLogFile($name), env('APP_LOG_LEVEL', 'error')),    // 文件日志管道
                                                       ],
                                                       [
                                                           new UidProcessor(),	// 日志唯一ID
                                                           new ProcessIdProcessor(),	// 进程号
                                                       ]);


        }

        return static::$_log_instance[$name];
    }

    /**
     * 获取日志文件地址
     * 日志文件为 $logName/YYYY-MM-DD.log
     *
     * @param string $logName 日志文件的最后一层目录
     *
     * @return string
     */
    private static function getLogFile(string $logName = ''): string
    {
        // 本地环境目录地址 ./storage目录
        // 其他根据 .env  APP_LOG_PATH定义获取
        if (env('APP_ENV') == 'local') {
            $path = storage_path('logs/local');
        } else {
            $path = env('APP_LOG_PATH');
        }

        if (substr($path, -1) != DIRECTORY_SEPARATOR) {
            $path .= DIRECTORY_SEPARATOR;
        }
        if ($logName) {
            $logName .= DIRECTORY_SEPARATOR;
        }

        return $path . $logName . date('Y-m-d') . '.log';
    }

    /**
     * 将method转换为logger level
     *
     * @param string $method
     *
     * @return int
     */
    private static function exchangeMethodToLogLevel(string $method): int
    {
        if (!in_array($method, ['debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency']))
        {
            $method = 'notice';
        }

        $method = strtoupper($method);
        switch ($method)
        {
            case 'INFO':
                $monologLeve = Logger::INFO;
                break;
            case 'NOTICE':
                $monologLeve = Logger::NOTICE;
                break;
            case 'WARNING':
                $monologLeve = Logger::WARNING;
                break;
            case 'ERROR':
                $monologLeve = Logger::ERROR;
                break;
            case 'CRITICAL':
                $monologLeve = Logger::CRITICAL;
                break;
            case 'ALERT':
                $monologLeve = Logger::ALERT;
                break;
            case 'EMERGENCY':
                $monologLeve = Logger::EMERGENCY;
                break;
            case 'DEBUG':
            default:
                $monologLeve = Logger::DEBUG;
                break;
        }

        return $monologLeve;
    }

    /**
     * 记录日志
     *
     * @param string       $logName
     * @param string       $method  log level
     * @param string|array $message 消息内容
     */
    public static function addLog(string $logName, string $method, $message)
    {
        if (!is_array($message))
        {
            $message = [$message];
        }

        static::getLogInstance($logName)->addRecord(self::exchangeMethodToLogLevel($method), 'content', $message);
    }
}